// import com.alibaba.druid.DbType;
// import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
// import com.alibaba.druid.sql.visitor.SQLASTVisitor;
// import com.alibaba.druid.util.FnvHash;

// import java.sql.Types;
// import java.util.Collections;
// import java.util.List;

#include "SQLMapDataType.h"
#include "expr/SQLCharExpr.h"
#include "../../utils/FnvHash.h"
#include "../../Exception/UnsupportedOperationException.h"
#include "../visitor/SQLASTVisitor.h"
#include "../../utils/Types.h"

SQLMapDataType_ptr SQLMapDataType::MAP_CHAR_CHAR = SQLMapDataType_ptr(new SQLMapDataType(SQLCharExpr::DATA_TYPE, SQLCharExpr::DATA_TYPE));

SQLMapDataType::SQLMapDataType()
{
}

SQLMapDataType::SQLMapDataType(SQLDataType_ptr keyType, SQLDataType_ptr valueType)
{
  this->setKeyType(keyType);
  this->setValueType(valueType);
}

SQLMapDataType::SQLMapDataType(SQLDataType_ptr keyType, SQLDataType_ptr valueType, DbType_ptr dbType)
{
  this->setKeyType(keyType);
  this->setValueType(valueType);
  this->dbType = dbType;
}

// @Override
string_ptr SQLMapDataType::getName()
{
  return make_string_ptr("MAP");
}

// @Override
long SQLMapDataType::nameHashCode64()
{
  return FnvHash::Constants::MAP;
}

// @Override
void SQLMapDataType::setName(string_ptr name)
{
  throw new UnsupportedOperationException();
}

// @Override
SQLExpr_list_ptr SQLMapDataType::getArguments()
{
  SQLExpr_list_ptr tmp = std::make_shared<std::list<SQLExpr_ptr>>();
  return tmp;
}

// @Override
BOOL_ptr SQLMapDataType::getWithTimeZone()
{
  // return nullptr;
  return BOOL::FALSE;
}

// @Override
void SQLMapDataType::setWithTimeZone(BOOL_ptr value)
{
  throw new UnsupportedOperationException();
}

// @Override
BOOL_ptr SQLMapDataType::isWithLocalTimeZone()
{
  return BOOL::FALSE;
}

// @Override
void SQLMapDataType::setWithLocalTimeZone(BOOL_ptr value)
{
  throw new UnsupportedOperationException();
}

// @Override
void SQLMapDataType::setDbType(DbType_ptr dbType)
{
  this->dbType = dbType;
}

// @Override
DbType_ptr SQLMapDataType::getDbType()
{
  return dbType;
}

// @Override
void SQLMapDataType::accept0(SQLASTVisitor_ptr visitor)
{
  if (visitor->visit(SharedObject(SQLMapDataType)))
  {
    acceptChild(visitor, keyType);
    acceptChild(visitor, valueType);
  }
  visitor->endVisit(SharedObject(SQLMapDataType));
}

SQLObject_ptr SQLMapDataType::clone()
{
  SQLObject_ptr clone_tmp = std::shared_ptr<SQLMapDataType>(new SQLMapDataType());
  std::shared_ptr<SQLMapDataType> x = std::dynamic_pointer_cast<SQLMapDataType>(clone_tmp);
  // SQLMapDataType x = new SQLMapDataType();
  x->dbType = dbType;

  if (keyType != nullptr)
  {
    x->setKeyType(std::dynamic_pointer_cast<SQLDataType>(keyType->clone()));
  }

  if (valueType != nullptr)
  {
    x->setValueType(std::dynamic_pointer_cast<SQLDataType>(valueType->clone()));
  }

  return x;
}

SQLDataType_ptr SQLMapDataType::getKeyType()
{
  return keyType;
}

void SQLMapDataType::setKeyType(SQLDataType_ptr x)
{
  if (x != nullptr)
  {
    x->setParent(SharedObject(SQLMapDataType));
  }
  this->keyType = x;
}

SQLDataType_ptr SQLMapDataType::getValueType()
{
  return valueType;
}

void SQLMapDataType::setValueType(SQLDataType_ptr x)
{
  if (x != nullptr)
  {
    x->setParent(SharedObject(SQLMapDataType));
  }
  this->valueType = x;
}

int SQLMapDataType::jdbcType()
{
  return Types::OTHER;
}

// @Override
BOOL_ptr SQLMapDataType::isInt()
{
  return BOOL::FALSE;
}

// @Override
BOOL_ptr SQLMapDataType::isNumberic()
{
  return BOOL::FALSE;
}

// @Override
BOOL_ptr SQLMapDataType::isString()
{
  return BOOL::FALSE;
}

// @Override
BOOL_ptr SQLMapDataType::hasKeyLength()
{
  return BOOL::FALSE;
}
